home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / linux / atari / source / source.lzh / atari-linux-0.01pl3 / fs / msdos / inode.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-05  |  13.3 KB  |  453 lines

  1. /*
  2.  *  linux/fs/msdos/inode.c
  3.  *
  4.  *  Written 1992,1993 by Werner Almesberger
  5.  */
  6.  
  7. /* ++roman: There was a wrong endianess conversion in
  8.  * msdos_write_inode() (start cluster was converted as long, not
  9.  * word).
  10.  */
  11.  
  12. #include <linux/msdos_fs.h>
  13. #include <linux/kernel.h>
  14. #include <linux/sched.h>
  15. #include <linux/errno.h>
  16. #include <linux/string.h>
  17. #include <linux/ctype.h>
  18. #include <linux/stat.h>
  19. #include <linux/locks.h>
  20.  
  21. #include <asm/segment.h>
  22.  
  23.  
  24. void msdos_put_inode(struct inode *inode)
  25. {
  26.     struct inode *depend;
  27.     struct super_block *sb;
  28.  
  29.     if (inode->i_nlink) {
  30.         if (MSDOS_I(inode)->i_busy) cache_inval_inode(inode);
  31.         return;
  32.     }
  33.     inode->i_size = 0;
  34.     msdos_truncate(inode);
  35.     depend = MSDOS_I(inode)->i_depend;
  36.     sb = inode->i_sb;
  37.     clear_inode(inode);
  38.     if (depend) {
  39.         if (MSDOS_I(depend)->i_old != inode) {
  40.             printk("Invalid link (0x%X): expected 0x%X, got 0x%X\n",
  41.                 (int) depend,(int) inode,(int) MSDOS_I(depend)->
  42.                 i_old);
  43.             fs_panic(sb,"...");
  44.             return;
  45.         }
  46.         MSDOS_I(depend)->i_old = NULL;
  47.         iput(depend);
  48.     }
  49. }
  50.  
  51.  
  52. void msdos_put_super(struct super_block *sb)
  53. {
  54.     cache_inval_dev(sb->s_dev);
  55.     lock_super(sb);
  56.     sb->s_dev = 0;
  57.     unlock_super(sb);
  58.     return;
  59. }
  60.  
  61.  
  62. static struct super_operations msdos_sops = { 
  63.     msdos_read_inode,
  64.     msdos_notify_change,
  65.     msdos_write_inode,
  66.     msdos_put_inode,
  67.     msdos_put_super,
  68.     NULL, /* added in 0.96c */
  69.     msdos_statfs,
  70.     NULL
  71. };
  72.  
  73.  
  74. static int parse_options(char *options,char *check,char *conversion,uid_t *uid,
  75.     gid_t *gid,int *umask,int *debug,int *fat,int *quiet)
  76. {
  77.     char *this_char,*value;
  78.  
  79.     *check = 'n';
  80.     *conversion = 'b';
  81.     *uid = current->uid;
  82.     *gid = current->gid;
  83.     *umask = current->umask;
  84.     *debug = *fat = *quiet = 0;
  85.     if (!options) return 1;
  86.     for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
  87.         if ((value = strchr(this_char,'=')) != NULL)
  88.             *value++ = 0;
  89.         if (!strcmp(this_char,"check") && value) {
  90.             if (value[0] && !value[1] && strchr("rns",*value))
  91.                 *check = *value;
  92.             else if (!strcmp(value,"relaxed")) *check = 'r';
  93.             else if (!strcmp(value,"normal")) *check = 'n';
  94.             else if (!strcmp(value,"strict")) *check = 's';
  95.             else return 0;
  96.         }
  97.         else if (!strcmp(this_char,"conv") && value) {
  98.             if (value[0] && !value[1] && strchr("bta",*value))
  99.                 *conversion = *value;
  100.             else if (!strcmp(value,"binary")) *conversion = 'b';
  101.             else if (!strcmp(value,"text")) *conversion = 't';
  102.             else if (!strcmp(value,"auto")) *conversion = 'a';
  103.             else return 0;
  104.         }
  105.         else if (!strcmp(this_char,"uid")) {
  106.             if (!value || !*value)
  107.                 return 0;
  108.             *uid = simple_strtoul(value,&value,0);
  109.             if (*value)
  110.                 return 0;
  111.         }
  112.         else if (!strcmp(this_char,"gid")) {
  113.             if (!value || !*value)
  114.                 return 0;
  115.             *gid = simple_strtoul(value,&value,0);
  116.             if (*value)
  117.                 return 0;
  118.         }
  119.         else if (!strcmp(this_char,"umask")) {
  120.             if (!value || !*value)
  121.                 return 0;
  122.             *umask = simple_strtoul(value,&value,8);
  123.             if (*value)
  124.                 return 0;
  125.         }
  126.         else if (!strcmp(this_char,"debug")) {
  127.             if (value) return 0;
  128.             *debug = 1;
  129.         }
  130.         else if (!strcmp(this_char,"fat")) {
  131.             if (!value || !*value)
  132.                 return 0;
  133.             *fat = simple_strtoul(value,&value,0);
  134.             if (*value || (*fat != 12 && *fat != 16))
  135.                 return 0;
  136.         }
  137.         else if (!strcmp(this_char,"quiet")) {
  138.             if (value) return 0;
  139.             *quiet = 1;
  140.         }
  141.         else return 0;
  142.     }
  143.     return 1;
  144. }
  145.  
  146.  
  147. /* Read the super block of an MS-DOS FS. */
  148.  
  149. struct super_block *msdos_read_super(struct super_block *s,void *data,
  150.                      int silent)
  151. {
  152.     struct buffer_head *bh;
  153.     struct msdos_boot_sector *b;
  154.     int data_sectors,logical_sector_size,sector_mult;
  155.     int debug,error,fat,quiet;
  156.     char check,conversion;
  157.     uid_t uid;
  158.     gid_t gid;
  159.     int umask;
  160.  
  161.     if (!parse_options((char *) data,&check,&conversion,&uid,&gid,&umask,
  162.         &debug,&fat,&quiet)) {
  163.         s->s_dev = 0;
  164.         return NULL;
  165.     }
  166.     cache_init();
  167.     lock_super(s);
  168.     bh = bread(s->s_dev, 0, BLOCK_SIZE);
  169.     unlock_super(s);
  170.     if (bh == NULL) {
  171.         s->s_dev = 0;
  172.         printk("MSDOS bread failed\n");
  173.         return NULL;
  174.     }
  175.     b = (struct msdos_boot_sector *) bh->b_data;
  176.     s->s_blocksize = 1024;    /* we cannot handle anything else yet */
  177.     s->s_blocksize_bits = 10;    /* we cannot handle anything else yet */
  178.  
  179. /*
  180.  * The DOS3 partition size limit is *not* 32M as many people think.  
  181.  * Instead, it is 64K sectors (with the usual sector size being
  182.  * 512 bytes, leading to a 32M limit).
  183.  * 
  184.  * DOS 3 partition managers got around this problem by faking a 
  185.  * larger sector size, ie treating multiple physical sectors as 
  186.  * a single logical sector.
  187.  * 
  188.  * We can accommodate this scheme by adjusting our cluster size,
  189.  * fat_start, and data_start by an appropriate value.
  190.  *
  191.  * (by Drew Eckhardt)
  192.  */
  193.  
  194. #define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0)
  195.     /* don't divide by zero */
  196.  
  197.     logical_sector_size = CF_LE_W(*(unsigned short *) &b->sector_size);
  198.     sector_mult = logical_sector_size >> SECTOR_BITS;
  199.     MSDOS_SB(s)->cluster_size = b->cluster_size*sector_mult;
  200.     MSDOS_SB(s)->fats = b->fats;
  201.     MSDOS_SB(s)->fat_start = CF_LE_W(b->reserved)*sector_mult;
  202.     MSDOS_SB(s)->fat_length = CF_LE_W(b->fat_length)*sector_mult;
  203.     MSDOS_SB(s)->dir_start = (CF_LE_W(b->reserved)+b->fats*CF_LE_W(
  204.         b->fat_length))*sector_mult;
  205.     MSDOS_SB(s)->dir_entries = CF_LE_W(*((unsigned short *) &b->dir_entries
  206.         ));
  207.     MSDOS_SB(s)->data_start = MSDOS_SB(s)->dir_start+ROUND_TO_MULTIPLE((
  208.         MSDOS_SB(s)->dir_entries << MSDOS_DIR_BITS) >> SECTOR_BITS,
  209.         sector_mult);
  210.     data_sectors = (CF_LE_W(*((unsigned short *) &b->sectors)) ?
  211.         CF_LE_W(*((unsigned short *) &b->sectors)) :
  212.         CF_LE_L(b->total_sect))*sector_mult-MSDOS_SB(s)->data_start;
  213.     error = !b->cluster_size || !sector_mult;
  214.     if (!error) {
  215.         MSDOS_SB(s)->clusters = b->cluster_size ? data_sectors/
  216.             b->cluster_size/sector_mult : 0;
  217.         MSDOS_SB(s)->fat_bits = fat ? fat : MSDOS_SB(s)->clusters >
  218.             MSDOS_FAT12 ? 16 : 12;
  219.         error = !MSDOS_SB(s)->fats || (MSDOS_SB(s)->dir_entries &
  220.             (MSDOS_DPS-1)) || MSDOS_SB(s)->clusters+2 > MSDOS_SB(s)->
  221.             fat_length*SECTOR_SIZE*8/MSDOS_SB(s)->fat_bits ||
  222.             (logical_sector_size & (SECTOR_SIZE-1)) || !b->secs_track ||
  223.             !b->heads;
  224.     }
  225.     brelse(bh);
  226.     if (error || debug) {
  227.         printk("[MS-DOS FS Rel. 12,FAT %d,check=%c,conv=%c,"
  228.             "uid=%d,gid=%d,umask=%03o%s]\n",MSDOS_SB(s)->fat_bits,check,
  229.             conversion,uid,gid,umask,MSDOS_CAN_BMAP(MSDOS_SB(s)) ?
  230.             ",bmap" : "");
  231.         printk("[me=0x%x,cs=%d,#f=%d,fs=%d,fl=%d,ds=%d,de=%d,data=%d,"
  232.             "se=%d,ts=%ld,ls=%d]\n",b->media,MSDOS_SB(s)->cluster_size,
  233.             MSDOS_SB(s)->fats,MSDOS_SB(s)->fat_start,MSDOS_SB(s)->
  234.             fat_length,MSDOS_SB(s)->dir_start,MSDOS_SB(s)->dir_entries,
  235.             MSDOS_SB(s)->data_start,CF_LE_W(*(unsigned short *) &b->
  236.             sectors),b->total_sect,logical_sector_size);
  237.     }
  238.     if (error) {
  239.         if (!silent)
  240.             printk("VFS: Can't find a valid MSDOS filesystem on dev 0x%04x.\n",
  241.                    s->s_dev);
  242.         s->s_dev = 0;
  243.         return NULL;
  244.     }
  245.     s->s_magic = MSDOS_SUPER_MAGIC;
  246.     MSDOS_SB(s)->name_check = check;
  247.     MSDOS_SB(s)->conversion = conversion;
  248.     /* set up enough so that it can read an inode */
  249.     s->s_op = &msdos_sops;
  250.     MSDOS_SB(s)->fs_uid = uid;
  251.     MSDOS_SB(s)->fs_gid = gid;
  252.     MSDOS_SB(s)->fs_umask = umask;
  253.     MSDOS_SB(s)->quiet = quiet;
  254.     MSDOS_SB(s)->free_clusters = -1; /* don't know yet */
  255.     MSDOS_SB(s)->fat_wait = NULL;
  256.     MSDOS_SB(s)->fat_lock = 0;
  257.     MSDOS_SB(s)->prev_free = 0;
  258.     if (!(s->s_mounted = iget(s,MSDOS_ROOT_INO))) {
  259.         s->s_dev = 0;
  260.         printk("get root inode failed\n");
  261.         return NULL;
  262.     }
  263.     return s;
  264. }
  265.  
  266.  
  267. void msdos_statfs(struct super_block *sb,struct statfs *buf)
  268. {
  269.     int free,nr;
  270.  
  271.     put_fs_long(sb->s_magic,&buf->f_type);
  272.     put_fs_long(MSDOS_SB(sb)->cluster_size*SECTOR_SIZE,&buf->f_bsize);
  273.     put_fs_long(MSDOS_SB(sb)->clusters,&buf->f_blocks);
  274.     lock_fat(sb);
  275.     if (MSDOS_SB(sb)->free_clusters != -1)
  276.         free = MSDOS_SB(sb)->free_clusters;
  277.     else {
  278.         free = 0;
  279.         for (nr = 2; nr < MSDOS_SB(sb)->clusters+2; nr++)
  280.             if (!fat_access(sb,nr,-1)) free++;
  281.         MSDOS_SB(sb)->free_clusters = free;
  282.     }
  283.     unlock_fat(sb);
  284.     put_fs_long(free,&buf->f_bfree);
  285.     put_fs_long(free,&buf->f_bavail);
  286.     put_fs_long(0,&buf->f_files);
  287.     put_fs_long(0,&buf->f_ffree);
  288.     put_fs_long(12,&buf->f_namelen);
  289. }
  290.  
  291.  
  292. int msdos_bmap(struct inode *inode,int block)
  293. {
  294.     struct msdos_sb_info *sb;
  295.     int cluster,offset;
  296.  
  297.     sb = MSDOS_SB(inode->i_sb);
  298.     if ((sb->cluster_size & 1) || (sb->data_start & 1)) return 0;
  299.     if (inode->i_ino == MSDOS_ROOT_INO) {
  300.         if (sb->dir_start & 1) return 0;
  301.         return (sb->dir_start >> 1)+block;
  302.     }
  303.     cluster = (block*2)/sb->cluster_size;
  304.     offset = (block*2) % sb->cluster_size;
  305.     if (!(cluster = get_cluster(inode,cluster))) return 0;
  306.     return ((cluster-2)*sb->cluster_size+sb->data_start+offset) >> 1;
  307. }
  308.  
  309.  
  310. void msdos_read_inode(struct inode *inode)
  311. {
  312.     struct buffer_head *bh;
  313.     struct msdos_dir_entry *raw_entry;
  314.     int nr;
  315.  
  316. /* printk("read inode %d\n",inode->i_ino); */
  317.     MSDOS_I(inode)->i_busy = 0;
  318.     MSDOS_I(inode)->i_depend = MSDOS_I(inode)->i_old = NULL;
  319.     MSDOS_I(inode)->i_binary = 1;
  320.     inode->i_uid = MSDOS_SB(inode->i_sb)->fs_uid;
  321.     inode->i_gid = MSDOS_SB(inode->i_sb)->fs_gid;
  322.     if (inode->i_ino == MSDOS_ROOT_INO) {
  323.         inode->i_mode = (S_IRWXUGO & ~MSDOS_SB(inode->i_sb)->fs_umask) |
  324.             S_IFDIR;
  325.         inode->i_op = &msdos_dir_inode_operations;
  326.         inode->i_nlink = msdos_subdirs(inode)+2;
  327.             /* subdirs (neither . nor ..) plus . and "self" */
  328.         inode->i_size = MSDOS_SB(inode->i_sb)->dir_entries*
  329.             sizeof(struct msdos_dir_entry);
  330.         inode->i_blksize = MSDOS_SB(inode->i_sb)->cluster_size*
  331.             SECTOR_SIZE;
  332.         inode->i_blocks = (inode->i_size+inode->i_blksize-1)/
  333.             inode->i_blksize*MSDOS_SB(inode->i_sb)->cluster_size;
  334.         MSDOS_I(inode)->i_start = 0;
  335.         MSDOS_I(inode)->i_attrs = 0;
  336.         inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
  337.         return;
  338.     }
  339.     if (!(bh = bread(inode->i_dev,inode->i_ino >> MSDOS_DPB_BITS,
  340.         BLOCK_SIZE))) {
  341.         printk("dev = 0x%04X, ino = %ld\n",inode->i_dev,inode->i_ino);
  342.         panic("msdos_read_inode: unable to read i-node block");
  343.     }
  344.     raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
  345.         [inode->i_ino & (MSDOS_DPB-1)];
  346.     if ((raw_entry->attr & ATTR_DIR) && !IS_FREE(raw_entry->name)) {
  347.         inode->i_mode = MSDOS_MKMODE(raw_entry->attr,S_IRWXUGO &
  348.             ~MSDOS_SB(inode->i_sb)->fs_umask) | S_IFDIR;
  349.         inode->i_op = &msdos_dir_inode_operations;
  350.         MSDOS_I(inode)->i_start = CF_LE_W(raw_entry->start);
  351.         inode->i_nlink = msdos_subdirs(inode);
  352.             /* includes .., compensating for "self" */
  353. #ifdef DEBUG
  354.         if (!inode->i_nlink) {
  355.             printk("directory %d: i_nlink == 0\n",inode->i_ino);
  356.             inode->i_nlink = 1;
  357.         }
  358. #endif
  359.         inode->i_size = 0;
  360.         if ((nr = CF_LE_W(raw_entry->start)) != 0)
  361.             while (nr != -1) {
  362.                 inode->i_size += SECTOR_SIZE*MSDOS_SB(inode->
  363.                     i_sb)->cluster_size;
  364.                 if (!(nr = fat_access(inode->i_sb,nr,-1))) {
  365.                     printk("Directory %ld: bad FAT\n",
  366.                         inode->i_ino);
  367.                     break;
  368.                 }
  369.             }
  370.     }
  371.     else {
  372.         inode->i_mode = MSDOS_MKMODE(raw_entry->attr,(IS_NOEXEC(inode)
  373.             ? S_IRUGO|S_IWUGO : S_IRWXUGO) & ~MSDOS_SB(inode->i_sb)->fs_umask) |
  374.             S_IFREG;
  375.         inode->i_op = MSDOS_CAN_BMAP(MSDOS_SB(inode->i_sb)) ? 
  376.             &msdos_file_inode_operations :
  377.             &msdos_file_inode_operations_no_bmap;
  378.         MSDOS_I(inode)->i_start = CF_LE_W(raw_entry->start);
  379.         inode->i_nlink = 1;
  380.         inode->i_size = CF_LE_L(raw_entry->size);
  381.     }
  382.     MSDOS_I(inode)->i_binary = is_binary(MSDOS_SB(inode->i_sb)->conversion,
  383.         raw_entry->ext);
  384.     MSDOS_I(inode)->i_attrs = raw_entry->attr & ATTR_UNUSED;
  385.     /* this is as close to the truth as we can get ... */
  386.     inode->i_blksize = MSDOS_SB(inode->i_sb)->cluster_size*SECTOR_SIZE;
  387.     inode->i_blocks = (inode->i_size+inode->i_blksize-1)/
  388.         inode->i_blksize*MSDOS_SB(inode->i_sb)->cluster_size;
  389.     inode->i_mtime = inode->i_atime = inode->i_ctime =
  390.         date_dos2unix(CF_LE_W(raw_entry->time),CF_LE_W(raw_entry->date));
  391.     brelse(bh);
  392. }
  393.  
  394.  
  395. void msdos_write_inode(struct inode *inode)
  396. {
  397.     struct buffer_head *bh;
  398.     struct msdos_dir_entry *raw_entry;
  399.  
  400.     inode->i_dirt = 0;
  401.     if (inode->i_ino == MSDOS_ROOT_INO || !inode->i_nlink) return;
  402.     if (!(bh = bread(inode->i_dev,inode->i_ino >> MSDOS_DPB_BITS,
  403.         BLOCK_SIZE))) {
  404.         printk("dev = 0x%04X, ino = %ld\n",inode->i_dev,inode->i_ino);
  405.         panic("msdos_write_inode: unable to read i-node block");
  406.     }
  407.     raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
  408.         [inode->i_ino & (MSDOS_DPB-1)];
  409.     if (S_ISDIR(inode->i_mode)) {
  410.         raw_entry->attr = ATTR_DIR;
  411.         raw_entry->size = 0;
  412.     }
  413.     else {
  414.         raw_entry->attr = ATTR_NONE;
  415.         raw_entry->size = CT_LE_L(inode->i_size);
  416.     }
  417.     raw_entry->attr |= MSDOS_MKATTR(inode->i_mode) |
  418.         MSDOS_I(inode)->i_attrs;
  419.     raw_entry->start = CT_LE_W(MSDOS_I(inode)->i_start);
  420.     date_unix2dos(inode->i_mtime,&raw_entry->time,&raw_entry->date);
  421.     raw_entry->time = CT_LE_W(raw_entry->time);
  422.     raw_entry->date = CT_LE_W(raw_entry->date);
  423.     bh->b_dirt = 1;
  424.     brelse(bh);
  425. }
  426.  
  427.  
  428. int msdos_notify_change(int flags,struct inode *inode)
  429. {
  430.     int error;
  431.  
  432.     error = 0;
  433.     if ((flags & NOTIFY_UIDGID) && (inode->i_uid != MSDOS_SB(inode->i_sb)->
  434.         fs_uid || inode->i_gid != MSDOS_SB(inode->i_sb)->fs_gid)) {
  435.         inode->i_uid = MSDOS_SB(inode->i_sb)->fs_uid;
  436.         inode->i_gid = MSDOS_SB(inode->i_sb)->fs_gid;
  437.         error = -EPERM;
  438.     }
  439.     if (!(flags & NOTIFY_MODE))
  440.         return MSDOS_SB(inode->i_sb)->quiet ? 0 : error;
  441.     if (inode->i_mode & ~MSDOS_VALID_MODE) {
  442.         inode->i_mode &= MSDOS_VALID_MODE;
  443.         error = -EPERM;
  444.     }
  445.     if (IS_NOEXEC(inode) && !S_ISDIR(inode->i_mode))
  446.         inode->i_mode &= S_IFMT | S_IRUGO | S_IWUGO;
  447.     else inode->i_mode |= S_IXUGO;
  448.     inode->i_mode = ((inode->i_mode & S_IFMT) | ((((inode->i_mode & S_IRWXU
  449.         & ~MSDOS_SB(inode->i_sb)->fs_umask) | S_IRUSR) >> 6)*S_IXUGO)) &
  450.         ~MSDOS_SB(inode->i_sb)->fs_umask;
  451.     return MSDOS_SB(inode->i_sb)->quiet ? 0 : error;
  452. }
  453.